package controller;

import databaseLayer.CustomerUpdate;
import databaseLayer.MoviesLookUp;
import databaseLayer.RecordLookUp;
import databaseLayer.UserLookUp;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import movieBean.Movie;
import movieBean.SeatPlan;
import movieBean.SingleMovie;
import userBean.PurchaseRecord;
import userBean.RegisteredCustomer;
import userBean.TicketingOfficer;
import userBean.UserIdentity;
import userBean.Visitor;

/**
 *
 * @author Sam
 */
public class Purchase extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        UserIdentity userIdentity;
        String topDisplayMsg = "";
        String address = "/purchaseMovieTickets.jsp";
        
        HttpSession session = request.getSession();
        if (session.isNew()) {
            //Identify user as a visitor
            userIdentity = new Visitor();
            session.setAttribute("userIdentity", (Visitor)userIdentity);
        }
        
        userIdentity = (UserIdentity)session.getAttribute("userIdentity");
        
        if (!(userIdentity.getUserType().equals("Visitor"))
                && !(userIdentity.getUserType().equals("RegisteredCustomer"))
                && !(userIdentity.getUserType().equals("TicketingOfficer"))) {
            
            address = "/close.jsp";
            String displayMsg = "Break-in is not allowed!";
            
            request.setAttribute("displayMsg", displayMsg);
        }
        else {
            Date currentTime = new Date();
            SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss z");

            String action = request.getParameter("action");

            if (action != null && action.equals("confirmPayment")) {
                address = "/close.jsp";
                String displayMsg = "";

                if (userIdentity.getUserType().equals("TicketingOfficer")) {
                    String unpaidRecordID = request.getParameter("unpaidRecordID");

                    if (unpaidRecordID == null || unpaidRecordID == "") {
                        displayMsg = "There is no unpaid request.";
                    }
                    else {
                        if (CustomerUpdate.isPurchasePaid(unpaidRecordID)) {
                            displayMsg = "Payment is already accepted!";
                        }
                        else {
                            CustomerUpdate.payPurchase(unpaidRecordID);
                            displayMsg = "Payment is accepted!";
                        }
                    }
                }
                else {
                    String unpaidRecordID = (String)session.getAttribute("unpaidRecordID");
                    PurchaseRecord unpaidRecord = (PurchaseRecord)session.getAttribute("unpaidRecord");

                    if ((unpaidRecordID == null || unpaidRecordID == "") && (unpaidRecord == null)) {
                        displayMsg = "You do not have unpaid request.";
                    }
                    else if ((unpaidRecordID != null && unpaidRecordID != "") && (unpaidRecord != null)) {
                        if (CustomerUpdate.isPurchasePaid(unpaidRecordID)) {
                            displayMsg = "Payment is already accepted!";
                        }
                        else {
                            String purchaseTimeStr = unpaidRecord.getPurchaseTime();

                            try {
                                Date purchaseTime = dateFormatter.parse(purchaseTimeStr);

                                GregorianCalendar tempCal = new GregorianCalendar();
                                tempCal.setTime(purchaseTime);
                                tempCal.add(GregorianCalendar.MINUTE, 5);

                                if (currentTime.before(tempCal.getTime())) {
                                    CustomerUpdate.payPurchase(unpaidRecordID);
                                    displayMsg = "Thank you for your purchase! Your payment is accepted!";
                                }
                                else {
                                    displayMsg = "5 min is passed! Payment is timed out!";
                                }

                                session.removeAttribute("unpaidRecordID");
                                session.removeAttribute("unpaidRecord");
                            }
                            catch (ParseException ex) {
                                displayMsg = "Data is invalid!";
                            }
                        }
                    }
                    else {
                        displayMsg = "Data is invalid!";
                    }
                }

                request.setAttribute("displayMsg", displayMsg);
            }
            else {
                String movieName = request.getParameter("movie");
                String slotID = request.getParameter("slotID");

                if ((movieName == null || movieName == "") || (slotID == null || slotID =="")) {
                    address = "/close.jsp";
                    String displayMsg = "Information is missing!";

                    request.setAttribute("displayMsg", displayMsg);
                }
                else {
                    SimpleDateFormat timeZoneFormatter = new SimpleDateFormat("z");
                    String timeZone = timeZoneFormatter.format(currentTime);

                    String initialTime = "0000/00/00 00:00:00 " + timeZone;
                    String endTime = "9999/99/99 23:59:59 " + timeZone;

                    Movie allThisMovie = MoviesLookUp.getMovie(movieName, initialTime, endTime);

                    SingleMovie thisMovie = new SingleMovie();
                    for (int i = 0; i < allThisMovie.getMovieSlot().length; i++) {
                        if ((allThisMovie.getMovieSlot())[i].getSlotID().equals(slotID)) {
                            thisMovie.setName(allThisMovie.getName());
                            thisMovie.setDescription(allThisMovie.getDescription());
                            thisMovie.setDuration(allThisMovie.getDuration());
                            thisMovie.setMovieSlot((allThisMovie.getMovieSlot())[i]);
                            thisMovie.setThumbnailPath(allThisMovie.getThumbnailPath());
                            thisMovie.setTrailerPath(allThisMovie.getTrailerPath());
                            break;
                        }
                    }

                    int houseNo = thisMovie.getMovieSlot().getHouse();
                    String includeHouse = "/house" + houseNo + ".jsp";
                    SeatPlan thisSeatPlan = MoviesLookUp.getSeatPlan(slotID);

                    if (action != null && action.equals("pay")) {
                        if (userIdentity.getUserType().equals("RegisteredCustomer")) {
                            String stillUnpaid = (String)session.getAttribute("unpaidRecordID");

                            if (stillUnpaid == null || stillUnpaid == "") {
                                boolean allSeatAvailable = true;
                                boolean positiveLP = true;
                                boolean trueAmount = true;

                                String userID = ((RegisteredCustomer)userIdentity).getId();
                                String seatStr = request.getParameter("seatNo");
                                String buyTime = dateFormatter.format(currentTime);
                                String money = request.getParameter("price");
                                String loyaltyPts = request.getParameter("loyaltyPts");

                                if ((seatStr == null || seatStr == "") || (money == null || money == "") || (loyaltyPts == null || loyaltyPts == "")) {
                                    topDisplayMsg = "Recevied Information is invalid!";
                                }
                                else {
                                    try {
                                        int moneyInt = Integer.parseInt(money);
                                        int loyaltyPtsInt = Integer.parseInt(loyaltyPts);
                                        int userLP = UserLookUp.getPoint(userID);
                                        
                                        if ((userLP - loyaltyPtsInt < 0)) {
                                            positiveLP = false;
                                        }

                                        String[] seatNoArr = seatStr.split(",");
                                        int[] selectedSeat = new int[seatNoArr.length];

                                        for (int i = 0;i < selectedSeat.length; i++) {
                                            selectedSeat[i] = Integer.parseInt(seatNoArr[i]);
                                            if (!((thisSeatPlan.getSeat())[selectedSeat[i] - 1].equals("availableSeat"))) {
                                                allSeatAvailable = false;
                                                break;
                                            }
                                        }

                                        if ((selectedSeat.length * thisMovie.getMovieSlot().getPrice()) != (moneyInt + loyaltyPtsInt)) {
                                            trueAmount = false;
                                        }

                                        if (!positiveLP) {
                                            topDisplayMsg = "You do not have enough loyalty point!";
                                        }
                                        else if (!allSeatAvailable) {
                                            topDisplayMsg = "Some of the selected seats cannot be bought!";
                                        }
                                        else if (!trueAmount) {
                                            topDisplayMsg = "Payment detail is invalid!";
                                        }
                                        else {
                                            String unpaidRecordID = CustomerUpdate.purchaseTicket(userID, selectedSeat, buyTime, moneyInt, loyaltyPtsInt, movieName, slotID);
                                            PurchaseRecord thisRecord = RecordLookUp.getARecord(unpaidRecordID);

                                            session.setAttribute("unpaidRecordID", unpaidRecordID);
                                            session.setAttribute("unpaidRecord", thisRecord);

                                            address = "/payment.jsp";
                                        }
                                    }
                                    catch (NumberFormatException e) {
                                        topDisplayMsg = "Recevied Information is invalid!";
                                    }
                                }
                            }
                            else {
                                topDisplayMsg = "You need to pay for the previous movie ticket(s) before you continue to purchase!";
                            }
                        }
                        else if (userIdentity.getUserType().equals("TicketingOfficer")) {
                            boolean allSeatAvailable = true;
                            boolean trueAmount = true;

                            String userID = ((TicketingOfficer)userIdentity).getId();
                            String seatStr = request.getParameter("seatNo");
                            String buyTime = dateFormatter.format(currentTime);
                            String money = request.getParameter("price");

                            if ((seatStr == null || seatStr == "") || (money == null || money == "")) {
                                topDisplayMsg = "Recevied Information is invalid!";
                            }
                            else {
                                try {
                                    int moneyInt = Integer.parseInt(money);
                                    int loyaltyPtsInt = 0;

                                    String[] seatNoArr = seatStr.split(",");
                                    int[] selectedSeat = new int[seatNoArr.length];

                                    for (int i = 0;i < selectedSeat.length; i++) {
                                        selectedSeat[i] = Integer.parseInt(seatNoArr[i]);
                                        if (!((thisSeatPlan.getSeat())[selectedSeat[i] - 1].equals("availableSeat"))) {
                                            allSeatAvailable = false;
                                            break;
                                        }
                                    }

                                    if ((selectedSeat.length * thisMovie.getMovieSlot().getPrice()) != (moneyInt + loyaltyPtsInt)) {
                                        trueAmount = false;
                                    }

                                    if (!allSeatAvailable) {
                                        topDisplayMsg = "Some of the selected seats cannot be bought!";
                                    }
                                    else if (!trueAmount) {
                                        topDisplayMsg = "Payment detail is invalid!";
                                    }
                                    else {
                                        String unpaidRecordID = CustomerUpdate.purchaseTicket(userID, selectedSeat, buyTime, moneyInt, loyaltyPtsInt, movieName, slotID);
                                        PurchaseRecord thisRecord = RecordLookUp.getARecord(unpaidRecordID);

                                        request.setAttribute("unpaidRecordID", unpaidRecordID);
                                        request.setAttribute("unpaidRecord", thisRecord);

                                        address = "/payment.jsp";
                                    }
                                }
                                catch (NumberFormatException e) {
                                    topDisplayMsg = "Recevied Information is invalid!";
                                }
                            }
                        }
                        else {
                            String stillUnpaid = (String)session.getAttribute("unpaidRecordID");

                            if (stillUnpaid == null || stillUnpaid == "") {
                                boolean allSeatAvailable = true;
                                boolean trueAmount = true;

                                String userID = "---";
                                String seatStr = request.getParameter("seatNo");
                                String buyTime = dateFormatter.format(currentTime);
                                String money = request.getParameter("price");

                                if ((seatStr == null || seatStr == "") || (money == null || money == "")) {
                                    topDisplayMsg = "Recevied Information is invalid!";
                                }
                                else {
                                    try {
                                        int moneyInt = Integer.parseInt(money);
                                        int loyaltyPtsInt = 0;

                                        String[] seatNoArr = seatStr.split(",");
                                        int[] selectedSeat = new int[seatNoArr.length];

                                        for (int i = 0;i < selectedSeat.length; i++) {
                                            selectedSeat[i] = Integer.parseInt(seatNoArr[i]);
                                            if (!((thisSeatPlan.getSeat())[selectedSeat[i] - 1].equals("availableSeat"))) {
                                                allSeatAvailable = false;
                                                break;
                                            }
                                        }

                                        if ((selectedSeat.length * thisMovie.getMovieSlot().getPrice()) != (moneyInt + loyaltyPtsInt)) {
                                            trueAmount = false;
                                        }

                                        if (!allSeatAvailable) {
                                            topDisplayMsg = "Some of the selected seats cannot be bought!";
                                        }
                                        else if (!trueAmount) {
                                            topDisplayMsg = "Payment detail is invalid!";
                                        }
                                        else {
                                            String unpaidRecordID = CustomerUpdate.purchaseTicket(userID, selectedSeat, buyTime, moneyInt, loyaltyPtsInt, movieName, slotID);
                                            PurchaseRecord thisRecord = RecordLookUp.getARecord(unpaidRecordID);

                                            session.setAttribute("unpaidRecordID", unpaidRecordID);
                                            session.setAttribute("unpaidRecord", thisRecord);

                                            address = "/payment.jsp";
                                        }
                                    }
                                    catch (NumberFormatException e) {
                                        topDisplayMsg = "Recevied Information is invalid!";
                                    }
                                }
                            }
                            else {
                                topDisplayMsg = "You need to pay for the previous movie ticket(s) before you continue to purchase!";
                            }
                        }
                    }

                    request.setAttribute("topDisplayMsg", topDisplayMsg);
                    request.setAttribute("thisMovie", thisMovie);
                    request.setAttribute("includeHouse", includeHouse);
                    request.setAttribute("thisSeatPlan", thisSeatPlan);
                    request.setAttribute("isRegistered", userIdentity.getUserType().equals("RegisteredCustomer")?"table-row":"none");

                    address = address + "?house=" + houseNo;
                }
            }
        }

        RequestDispatcher dispatcher = request.getRequestDispatcher(address);
        dispatcher.forward(request, response);
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
